import { Injectable } from '@nestjs/common';
import { ConfigService } from '@nestjs/config';
import * as moment from 'moment';
import * as crypto from 'crypto';
import { HttpService } from '@nestjs/axios';
import { catchError, map, throwError } from 'rxjs';

@Injectable()
export class CosStsService {
  private cosConfig: {
    secretId: string;
    secretKey: string;
    bucket: string;
    region: string;
  };

  constructor(private config: ConfigService, private httpService: HttpService) {
    this.cosConfig = {
      secretId: this.config.get<string>('SECRET_ID'),
      secretKey: this.config.get<string>('SECRET_KEY'),
      bucket: this.config.get<string>('BUCKET'),
      region: this.config.get<string>('REGION'),
    };
  }

  /**
   * 临时密钥服务
   * @param ext
   * @returns
   */
  async getStsCredentials(ext: string, path: string) {
    const { bucket, region, secretId, secretKey } = this.cosConfig;

    // 开始计算凭证
    const cosHost = `${bucket}.cos.${region}.myqcloud.com`;
    const cosKey = this.generateCosKey(ext, path);

    const now = Math.round(Date.now() / 1000);
    const exp = now + 900;
    const qKeyTime = now + ';' + exp;
    const qSignAlgorithm = 'sha1';

    // 生成上传要用的 policy
    const policy = JSON.stringify({
      expiration: new Date(exp * 1000).toISOString(),
      conditions: [
        { 'q-sign-algorithm': qSignAlgorithm },
        { 'q-ak': secretId },
        { 'q-sign-time': qKeyTime },
        { bucket: bucket },
        { key: cosKey },
      ],
    });

    // 生成 SignKey
    const signKey = crypto.createHmac('sha1', secretKey).update(qKeyTime).digest('hex');
    // 生成 StringToSign
    const stringToSign = crypto.createHash('sha1').update(policy).digest('hex');
    // 生成 Signature
    const qSignature = crypto.createHmac('sha1', signKey).update(stringToSign).digest('hex');

    return {
      cosHost: cosHost,
      cosKey: cosKey,
      policy: Buffer.from(policy).toString('base64'),
      qSignAlgorithm: qSignAlgorithm,
      qAk: secretId,
      qKeyTime: qKeyTime,
      qSignature: qSignature,
    };
  }

  /**
   * 生成要上传的 COS 文件路径文件名
   * @param ext 文件后缀
   * @returns
   */
  generateCosKey(ext: string, path: string) {
    const folder = moment().format('YYYYMMDD');
    const ymd = moment().format('YYYYMMDD_HHmmss_');
    const r = ('000000' + Math.random() * 1000000).slice(-6);
    const cosKey = `${path}/${folder}/IMG_${ymd}_${r}.${ext}`;
    return cosKey;
  }

  /**
   * 删除COS文件
   * @param cosKey 文件路径
   * @returns
   */
  deleteObject(cosKey) {
    const { bucket, region, secretId, secretKey } = this.cosConfig;

    // 构造删除请求的 URL
    const url = `https://${bucket}.cos.${region}.myqcloud.com/${cosKey}`;

    // 计算 Authorization 签名
    const now = Math.round(Date.now() / 1000);
    const exp = now + 900; // 设置签名有效期
    const qKeyTime = `${now};${exp}`;

    // 生成 SignKey
    const signKey = crypto.createHmac('sha1', secretKey).update(qKeyTime).digest('hex');

    const httpString = `delete\n/${cosKey}\n\nhost=${bucket}.cos.${region}.myqcloud.com\n`;
    const sha1edHttpString = crypto.createHash('sha1').update(httpString).digest('hex');
    const stringToSign = `sha1\n${qKeyTime}\n${sha1edHttpString}\n`;

    // 生成 Signature
    const signature = crypto.createHmac('sha1', signKey).update(stringToSign).digest('hex');

    const authHeader = `q-sign-algorithm=sha1&q-ak=${secretId}&q-sign-time=${qKeyTime}&q-key-time=${qKeyTime}&q-header-list=host&q-url-param-list=&q-signature=${signature}`;

    // 发送删除请求
    return this.httpService
      .delete(url, {
        headers: {
          Authorization: authHeader,
          Host: `${bucket}.cos.${region}.myqcloud.com`,
        },
      })
      .pipe(
        map((response) => response.data),
        catchError((error) =>
          throwError(() => new Error(`Error deleting object: ${error.message}`)),
        ),
      );
  }
}
